/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 * Origin source from MaNGOS(GPL2).
 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
 */

#ifndef __WORLD_SOCKET_H__
#define __WORLD_SOCKET_H__

#include "Common.h"

#include "ace/Svc_Handler.h"
#include "ace/SOCK_Stream.h"


#include "WorldPacket.h"

namespace PQServiceCore
{
	/// Handler that can communicate over stream sockets.
	typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> WorldHandler;

	/**
	 * WorldSocket.
	 *
	 * This class is responsible for the communication with
	 * remote clients.
	 * Most methods return -1 on failure.
	 * The class uses reference counting.
	 *
	 * For output the class uses one buffer (64K usually) and
	 * a queue where it stores packet if there is no place on
	 * the queue. The reason this is done, is because the server
	 * does really a lot of small-size writes to it, and it doesn't
	 * scale well to allocate memory for every. When something is
	 * written to the output buffer the socket is not immediately
	 * activated for output (again for the same reason), there
	 * is 10ms celling (thats why there is Update() method).
	 * This concept is similar to TCP_CORK, but TCP_CORK
	 * uses 200ms celling. As result overhead generated by
	 * sending packets from "producer" threads is minimal,
	 * and doing a lot of writes with small size is tolerated.
	 *
	 * The calls to Update () method are managed by WorldSocketMgr
	 * and ReactorRunnable.
	 *
	 * For input ,the class uses one 1024 bytes buffer on stack
	 * to which it does recv() calls. And then received data is
	 * distributed where its needed. 1024 matches pretty well the
	 * traffic generated by client for now.
	 *
	 * The input/output do speculative reads/writes (AKA it tryes
	 * to read all data available in the kernel buffer or tryes to
	 * write everything available in userspace buffer),
	 * which is ok for using with Level and Edge Triggered IO
	 * notification.
	 *
	 */
	class WorldSocket
		: protected WorldHandler
	{
	public:
		/// Get address of connected peer.
        const std::string& GetRemoteAddress(void) const;

		/// Add reference to this object.
        long AddReference(void);
		/// Remove reference to this object.
        long RemoveReference(void);

		void CloseSocket();

		/// Send A packet on the socket, this function is reentrant.
        /// @param packet packet to send
        /// @return -1 of failure
        int SendPacket (const WorldPacket& packet);

		 /// Check if socket is closed.
        bool isClosed (void) const;
	private:

	};
}

#endif
